package socket

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"klotski/pkg"
	"klotski/pojo"
	"klotski/socket/observer/impl"
	impl2 "klotski/socket/subject/impl"
	"log"
	"net/http"
	"time"
)

//// Hub 保证这里的hub变量是唯一的，并且所有的Client对象操作的是同一个

func WsHandle(hub *pojo.HupCenter) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//将短连接 升级成 长连接-建立WebSocket通信
		upgrade := websocket.Upgrader{
			ReadBufferSize:  1024,
			WriteBufferSize: 1024,
			CheckOrigin: func(r *http.Request) bool {
				return true
			},
		}

		conn, err := upgrade.Upgrade(w, r, nil)
		if err != nil {
			log.Println("conn错误", err)
			return
		}

		fmt.Println("远程主机连接成功 IP为", conn.RemoteAddr())
		//进行client的初始化操作
		client := &pojo.Client{User: &pojo.User{}, Hub: &pojo.HupCenter{}} //非字段不要为nil
		client.Hub = hub
		client.User.UserConn = conn
		client.User.HealthCheck = time.Now().Add(time.Duration(pkg.HeartCheckSecond) * time.Second) //健康时间

		//计时器 : 如果用户规定秒内没有完成用户认证，则直接断开连接
		time.AfterFunc(time.Duration(pkg.UserAuthSecond)*time.Second, func() {
			if !client.User.UserCer {
				fmt.Println("用户认证失败，关闭连接")
				client.User.Close()
			}
		})

		//接受信息 根据信息类型进行分别处理
		//go Controller(client)
		Controller(client)
	}
}

func Controller(client *pojo.Client) {
	defer func() {
		client.Hub.UnRegister <- client
	}()

	//信息中枢这边需要改一下,改成订阅者发布者模式，而不是单一的Switch、Case
	//1. 在信息中枢处根据消息类型进行特定的处理
	controller := new(impl2.Controller)

	certificationObserver := new(impl.CertificationObserver)
	createRoomObserver := new(impl.CreateRoomObserver)
	joinRoomObserver := new(impl.JoinRoomObserver)
	refreshScoreObserver := new(impl.RefreshScoreObserver)
	gameOverObserver := new(impl.GameOverObserver)
	discontinueQuitObserver := new(impl.DiscontinueQuitObserver)
	heartCheckObserver := new(impl.HeartCheckObserver)
	controller.AddProcess(certificationObserver, createRoomObserver, joinRoomObserver,
		refreshScoreObserver, gameOverObserver, discontinueQuitObserver, heartCheckObserver)

	for {
		_, p, err := client.User.UserConn.ReadMessage()
		if err != nil {
			if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
				//用户主动给关闭连接后的输出
				log.Println("WebSocket closed")
			} else {
				//服务器主动断开走这个，从一个断开的连接中读取信息
				log.Println("server.go conn.ReadMessage 读取信息错误", err)
			}
			return
		}

		var requestPkg pojo.RequestPkg
		err = json.Unmarshal(p, &requestPkg)
		if err != nil {
			fmt.Println("websocket反序列化失败", err)
			return
		}

		//观察者模式，通知所有的订阅者
		controller.Notify(client, &requestPkg)
	}

}
